/*
 * JsonrpcProcessor.cpp
 *
 *  Created on: Apr 18, 2017
 *      Author: zhangjf
 */

#include <Poco/JSON/Object.h>
#include <Poco/JSON/Parser.h>
#include <Poco/AutoPtr.h>
#include <Poco/Dynamic/Var.h>
#include <Poco/Util/Application.h>
#include "Poco/ErrorHandler.h"

using namespace Poco;
using namespace Poco::JSON;
using namespace Poco::Dynamic;
using namespace Poco::Util;

#include "Helper.h"
#include "JsonrpcProcessor.h"

namespace util
{

JsonrpcProcessor::JsonrpcProcessor()
{
	// TODO Auto-generated constructor stub

}

JsonrpcProcessor::~JsonrpcProcessor()
{
	// TODO Auto-generated destructor stub
}

bool JsonrpcProcessor::parseJsonrpc(const std::string& strReq, JsonrpcParams& params)
{
	params.blRet = false;
	int errCode = 0;
	std::string errMsg;

	Parser parser;
	Object::Ptr joReq;

	try
	{
		std::string strReq1 = "{\"jsonrpc\":\"2.0\", \"method\":\"Login\", \"params\":{\"user\":\"user\", \"passwd\":\"123456\"}, \"id\":7}";
		Var varReq = parser.parse(strReq);
		joReq = varReq.extract<Object::Ptr>();
		if (joReq->has("jsonrpc"))
		{
			params.strVer = joReq->getValue<std::string>("jsonrpc");
			if (joReq->has("method"))
			{
				params.strMethod = joReq->getValue<std::string>("method");

				if (joReq->has("params"))
				{
					params.joParams = joReq->getObject("params");

					params.id = -1;
					if (joReq->has("id"))
					{
						params.id = joReq->getValue<int>("id");
						params.blNotif = false;
					}
					else
						params.blNotif = true;

					params.blRet = true;
				}
				else
				{
					errCode = -32600;
					errMsg = "Invalid Request : not found params tag";
				}
			}
			else
			{
				errCode = -32600;
				errMsg = "Invalid Request : not found method tag";
			}
		}
		else
		{
			errCode = -32600;
			errMsg = "Invalid Request: not found jsonrpc tag";
		}
	}
	catch(JSONException& exc)
	{
		errCode = -32700;
		errMsg = exc.displayText();
	}
	catch(...)
	{
		errCode = -32700;
		errMsg = "Invalid Request: unhandled exception has occurred.";
	}

	if (!params.blRet)
	{
		params.joResult.set("code", errCode);
		params.joResult.set("message", errMsg);
	}

	return params.blRet;
}

bool JsonrpcProcessor::checkParams(JsonrpcParams& params)
{
	int errCode = 0;
	std::string errMsg;

	params.blRet = false;
	do
	{
		if (params.strVer != "2.0")
		{
			errCode = -32603;
			errMsg = "Invalid jsonrpc version(" + params.strVer + ")";
			break;
		}

		doCheckParams(this, params);
		if (params.blRet == false)
			break;

		params.blRet = true;
	} while(false);

	if (params.blRet == false)
	{
		Object joError;
		joError.set("code", errCode);
		joError.set("message", errMsg);

		params.joResult.set("error", joError);
	}

	return params.blRet;
}

bool JsonrpcProcessor::process(const std::string& strReq, Object& joResp, bool& blNotif)
{
	JsonrpcParams params;

	params.blRet = false;
	do
	{
		if ((params.blRet = parseJsonrpc(strReq, params)) == false)
		{
			//poco_information(Application::instance().logger(), "aaaaaaaaaaaaaaaaaaaaaaaaaaa");
			break;
		}

		if (checkParams(params) == false)
		{
			//poco_information(Application::instance().logger(), "bbbbbbbbbbbbbbbbb");
			break;
		}

		doRunJsonrpcMethod(this, params);
		if (params.blRet == false)
		{
			//poco_information(Application::instance().logger(), "cccccccccccccccccccccccccccccc");
			break;
		}

		params.blRet = true;
	} while (0);

	joResp.set("jsonrpc", "2.0");
	if (!params.blNotif)
		joResp.set("id", params.id);

	blNotif = params.blNotif;

	if (params.blRet == true)
	{
		joResp.set("result", params.joResult);
	}
	else
	{
		joResp.set("error", params.joResult);
	}

	return params.blRet;
}

}	// endof namespsace util
